package org.liaohailong.library.widget.header;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.liaohailong.library.R;

import java.util.LinkedList;

/**
 * Author: Victor
 * Date: 2019/5/17 9:17
 * Description: 头部内容布局，有且仅有两个View，第一个为HeaderView，第二个为ContentView
 * 与{@link HeaderScrollView}搭配使用
 */
public class HeaderContentLayout extends ViewGroup {
    private static final int CHILD_COUNT = 2;

    private View mHeaderView;
    private View mContentView;

    private int mHeaderHeight = 0;
    private int mContentHeight = 0;
    private int mTotalHeight = 0;

    public HeaderContentLayout(Context context) {
        this(context, null);
    }

    public HeaderContentLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HeaderContentLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() < CHILD_COUNT) {
            throw new IllegalArgumentException("you should add header view and content view on this layout!");
        }
        mHeaderView = getChildAt(0);
        mContentView = getChildAt(1);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MLayoutParams(p);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

        measureChildWithMargins(mHeaderView, widthMeasureSpec, 0, heightMeasureSpec, 0);
        int headerWidth = mHeaderView.getMeasuredWidth();
        int headerHeight = mHeaderView.getMeasuredHeight();

        LayoutParams contentLayoutParams = mContentView.getLayoutParams();
        int contentWidth = getLength(contentLayoutParams.width, parentWidth);
        int contentHeight = getLength(contentLayoutParams.height, parentHeight);
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY);
        mContentView.measure(widthMeasureSpec, heightMeasureSpec);

        int totalWidth = Math.max(headerWidth, contentWidth);
        int totalHeight = headerHeight + contentHeight;
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(totalWidth, MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mHeaderHeight = headerHeight;
        mContentHeight = contentHeight;
        mTotalHeight = totalHeight;
    }

    private int getLength(int layoutLength, int parentLength) {
        return LayoutParams.WRAP_CONTENT == layoutLength || LayoutParams.MATCH_PARENT == layoutLength ? parentLength : layoutLength;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int measuredWidth = mHeaderView.getMeasuredWidth();
        int measuredHeight = mHeaderView.getMeasuredHeight();
        int headerBottom = measuredHeight;
        mHeaderView.layout(0, 0, measuredWidth, headerBottom);

        measuredWidth = mContentView.getMeasuredWidth();
        measuredHeight = mContentView.getMeasuredHeight();
        int contentTop = headerBottom;
        int contentBottom = headerBottom + measuredHeight;
        mContentView.layout(0, contentTop, measuredWidth, contentBottom);
    }

    public int getHeaderHeight() {
        return mHeaderHeight;
    }

    public int getContentHeight() {
        return mContentHeight;
    }

    public int getTotalHeight() {
        return mTotalHeight;
    }


    public boolean isHeaderDisallowInterceptTouchEvent() {
        LayoutParams layoutParams = mHeaderView.getLayoutParams();
        if (layoutParams instanceof MLayoutParams) {
            MLayoutParams lp = (MLayoutParams) layoutParams;
            // 1表示一直都可滑动，要求父容器不拦截触点事件
            return lp.scrollMode == 1;
        }
        return false;
    }

    public boolean isTouchInHeaderArea(int x, int y, int scrollY) {
        if (mHeaderView == null) return false;

        int left = mHeaderView.getLeft();
        int right = mHeaderView.getRight();
        if (x > right || x < left) return false; // 判断水平方向是否在范围内
        int top = mHeaderView.getTop() - scrollY;
        int bottom = mHeaderView.getBottom() - scrollY;
        if (y > bottom || y < top) return false; // 判断垂直方向是否在范围内
        return true;
    }

    private final LinkedList<View> tempList = new LinkedList<>();
    private final int[] location = new int[2];
    private final Rect rect = new Rect();

    public boolean canContentScrollDown(float rawX, float rawY) {
        // 1，找出所有命中点击区域的view
        tempList.clear();
        testArea(mContentView, rawX, rawY, tempList);

        // 2，判断是否能够下滑
        while (!tempList.isEmpty()) {
            // 从后面开始，效率更高
            View view = tempList.removeLast();
            if (view.canScrollVertically(-1)) {
                return true;
            }
        }
        return false;
    }

    private void testArea(@NonNull View target, float rawX, float rawY,
                          @NonNull LinkedList<View> views) {
        target.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + target.getMeasuredWidth();
        int bottom = top + target.getMeasuredHeight();
        rect.set(left, top, right, bottom);
        if (rect.contains((int) rawX, (int) rawY)) {
            views.addLast(target);

            if (target instanceof ViewGroup) {
                ViewGroup parent = (ViewGroup) target;
                for (int i = 0; i < parent.getChildCount(); i++) {
                    View child = parent.getChildAt(i);
                    testArea(child, rawX, rawY, views);
                }
            }
        }
    }


    public static class MLayoutParams extends MarginLayoutParams {

        /**
         * 滑动模式：
         * 0 不可滑动
         * 1 一直都可滑动
         */
        private int scrollMode;

        public MLayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);

            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.HeaderContentLayout_Layout);
            scrollMode = a.getInteger(R.styleable.HeaderContentLayout_Layout_scroll_mode, 0);
            a.recycle();
        }

        public MLayoutParams(int width, int height) {
            super(width, height);
        }

        public MLayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public MLayoutParams(LayoutParams source) {
            super(source);
        }


        public void setScrollMode(int scrollMode) {
            this.scrollMode = scrollMode;
        }

        public int getScrollMode() {
            return scrollMode;
        }
    }

}
